package com.ld.shieldsb.common.composition.util;

import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;

import org.mindrot.jbcrypt.BCrypt;

import com.ld.shieldsb.common.core.encryptor.DesEncryptor;
import com.ld.shieldsb.common.core.encryptor.EncodeUtils;
import com.ld.shieldsb.common.core.encryptor.EorEncryptor;
import com.ld.shieldsb.common.core.encryptor.Md5Encryptor;
import com.ld.shieldsb.common.core.encryptor.Sha1Encryptor;
import com.ld.shieldsb.common.core.util.StringUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * 加密解密工具类，AES，DES，建议在项目中new对象
 * 
 * @ClassName SecurityService
 * @author <a href="mailto:donggongai@126.com" target="_blank">kevin</a>
 * @date 2016年8月25日 下午2:54:43
 *
 */
@Slf4j
public class SecurityUtil {
    private static String simpleSecretKeyRw = null; // "wefoundlove"; // 简单加密的密钥（读写），在具体项目中赋值
    private static String simpleSecretKeyR = null; // "wefoundlove_r"; // 简单加密的密钥（只读），在具体项目中赋值
    private static String desSecretKey = null; // "we_found_love"; // DES加密的密钥，在具体项目中赋值
    private static Integer eorSecretKeyR = null; // // 异或运算的密钥（只读），在具体项目中赋值

    private SecurityUtil() {
        throw new IllegalStateException("该类不可初始化");
    }

    /**
     * 
     * SHA1加密（不可逆）
     * 
     * @Title SHA1
     * @param data
     *            要加密字符
     * @return
     * @throws NoSuchAlgorithmException
     *             String
     */
    public static final String sha1(String data) {
        byte[] b = Sha1Encryptor.sha1(data.getBytes(StandardCharsets.UTF_8));
        return EncodeUtils.encodeHex(b);
    }

    /**
     * 
     * MD5加密（不可逆）
     * 
     * @Title MD5
     * @param data
     *            要加密字符
     * @return
     * @throws NoSuchAlgorithmException
     *             String
     */
    public static final String md5(String data) {
        byte[] b = Md5Encryptor.md5(data.getBytes(StandardCharsets.UTF_8));
        return EncodeUtils.encodeHex(b);
    }

    /**
     * 
     * 用户提交信息加密方式
     * 
     * @Title encryptIn
     * @param strIn
     *            字符串
     * @return
     * @throws Exception
     *             String
     */
    public static final String desEncrypt(String strIn) {
        if (desSecretKey == null) {
            log.error("DES_SECRET_KEY未赋值，请在项目中赋值！");
        }
        return DesEncryptor.encode(strIn, desSecretKey);
    }

    /**
     * 
     * 用户提交信息解密方式
     * 
     * @Title encryptIn
     * @param strIn
     *            字符串
     * @return
     * @throws Exception
     *             String
     */
    public static final String desDecrypt(String strIn) {
        if (desSecretKey == null) {
            log.error("DES_SECRET_KEY未赋值，请在项目中赋值！");
        }
        return DesEncryptor.decode(strIn, desSecretKey);
    }

    /**
     * bcrypt加密（使用了bcrypt hash算法）
     * 
     * @Title bcryptEncrypt
     * @author 吕凯
     * @date 2018年12月5日 上午11:27:46
     * @param strIn
     * @return String
     */
    public static final String bcryptEncrypt(String plaintext) {
        String salt = "$2a$10$" + StringUtils.getRandomStr(23); // 不少于30位，前7位固定
        if (log.isDebugEnabled()) {
            log.debug("salt:" + salt);
        }
        return BCrypt.hashpw(plaintext, salt);
    }

    /**
     * bcrypt算法加密过的文本是否匹配
     * 
     * @Title bcryptMatch
     * @author 吕凯
     * @date 2018年12月5日 上午11:34:12
     * @param plaintext
     * @param hashed
     * @return
     * @throws Exception
     *             boolean
     */
    public static final boolean bcryptMatch(String plaintext, String hashed) {
        return BCrypt.checkpw(plaintext, hashed);
    }

    /**
     * 
     * 简单加密，会保存的用此方法（DES，安全等级要求不高的情况）
     * 
     * @Title encryptIn
     * @param strIn
     *            字符串
     * @return
     * @throws Exception
     *             String
     */
    public static final String simpleEncrypt(String strIn) {
        return simpleWriteEncrypt(strIn);
    }

    public static final String simpleWriteEncrypt(String strIn) {
        if (!checkSimpleSecretKeyRw()) {
            return strIn;
        }
        return DesEncryptor.encode(strIn, simpleSecretKeyRw);
    }

    /**
     * 检查SIMPLE_SECRET_KEY_RW赋值情况
     * 
     * @Title checkSimpleSecretKeyRw
     * @author 吕凯
     * @date 2021年4月29日 下午1:57:00 void
     */
    private static boolean checkSimpleSecretKeyRw() {
        if (simpleSecretKeyRw == null) {
            log.error("simpleSecretKeyRw未赋值，请在项目中赋值！");
            return false;
        }
        return true;
    }

    /**
     * 
     * 简单解密，会保存的用此方法（DES，安全等级要求不高的情况）
     * 
     * @Title encryptIn
     * @param strIn
     *            字符串
     * @return
     * @throws Exception
     *             String
     */
    public static final String simpleDecrypt(String strIn) {
        return simpleWriteDecrypt(strIn);
    }

    public static final String simpleWriteDecrypt(String strIn) {
        if (!checkSimpleSecretKeyRw()) {
            return strIn;
        }
        return DesEncryptor.decode(strIn, simpleSecretKeyRw);
    }

    /**
     * 
     * 简单加密，只读取的用此方法，注意可能保存的一定不能使用此方法（DES，安全等级要求不高的情况）
     * 
     * @Title simpleReadEncrypt
     * @author 吕凯
     * @date 2019年8月2日 下午4:59:01
     * @param strIn
     * @return String
     */
    public static final String simpleReadEncrypt(String strIn) {
        if (!checkSimpleSecretKeyR()) {
            return strIn;
        }
        return DesEncryptor.encode(strIn, simpleSecretKeyR);
    }

    /**
     * 检查simpleSecretKeyR赋值情况
     * 
     * @Title checkSimpleSecretKeyR
     * @author 吕凯
     * @date 2021年4月29日 下午1:57:54 void
     */
    private static boolean checkSimpleSecretKeyR() {
        if (simpleSecretKeyR == null) {
            log.error("simpleSecretKeyR未赋值，请在项目中赋值！");
            return false;
        }
        return true;
    }

    /**
     * 
     * 简单解密，只读取的用此方法，注意可能保存的一定不能使用此方法（DES，安全等级要求不高的情况）
     * 
     * @Title simpleReadDecrypt
     * @author 吕凯
     * @date 2019年8月2日 下午4:59:20
     * @param strIn
     * @return String
     */
    public static final String simpleReadDecrypt(String strIn) {
        if (!checkSimpleSecretKeyR()) {
            return strIn;
        }
        return DesEncryptor.decode(strIn, simpleSecretKeyR);
    }

    /**
     * 
     * 查询加密（异或），只读取的用此方法，注意可能保存的一定不能使用此方法（DES，安全等级要求不高的情况）
     * 
     * @Title queryEncrypt
     * @author 吕凯
     * @date 2019年8月5日 上午9:24:56
     * @param strIn
     * @return String
     */
    public static final String queryEncrypt(String strIn) {
        if (!checkSimpleSecretKeyR()) {
            return strIn;
        }
        return EorEncryptor.encode(strIn, eorSecretKeyR);
    }

    /**
     * 查询解密（异或），只读取的用此方法，注意可能保存的一定不能使用此方法（DES，安全等级要求不高的情况）
     * 
     * @Title queryDecrypt
     * @author 吕凯
     * @date 2019年8月5日 上午9:24:43
     * @param strIn
     * @return String
     */
    public static final String queryDecrypt(String strIn) {
        if (eorSecretKeyR == null) {
            log.error("eorSecretKeyR未赋值，请在项目中赋值！");
            return strIn;
        }
        return EorEncryptor.decode(strIn, eorSecretKeyR);
    }

    public static String getSimpleSecretKeyRw() {
        return simpleSecretKeyRw;
    }

    public static void setSimpleSecretKeyRw(String simpleSecretKeyRw) {
        SecurityUtil.simpleSecretKeyRw = simpleSecretKeyRw;
    }

    public static String getSimpleSecretKeyR() {
        return simpleSecretKeyR;
    }

    public static void setSimpleSecretKeyR(String simpleSecretKeyR) {
        SecurityUtil.simpleSecretKeyR = simpleSecretKeyR;
    }

    public static String getDesSecretKey() {
        return desSecretKey;
    }

    public static void setDesSecretKey(String desSecretKey) {
        SecurityUtil.desSecretKey = desSecretKey;
    }

    public static Integer getEorSecretKeyR() {
        return eorSecretKeyR;
    }

    public static void setEorSecretKeyR(Integer eorSecretKeyR) {
        SecurityUtil.eorSecretKeyR = eorSecretKeyR;
    }

}
